import sys
import time

from selenium.common import NoSuchElementException
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver

from libs.image import ImageTool
from libs.log import Log
from libs.movement import Movement, KeyCode


class WebDriverAction:
    def __init__(self, driver: WebDriver, debug=False, user_id=None):
        self.driver = driver
        self.user_id = user_id
        self.movement = Movement(driver)
        self.image_tool = ImageTool(driver)
        self.tc_image = 'terra_center.png'
        # self.tc_image = 'terra_center_chris.png'
        # self.tc_image = 'terra_center_new_year.png'
        self.debug = debug

    def writeln(self, msg):
        if self.debug:
            print(msg, flush=True)

    def write(self, msg):
        if self.debug:
            print(msg, end="", flush=True)

    def find_element(self, by, value, element_name, seconds=30):
        self.write(f"find_element {element_name}")
        for _ in range(seconds):
            try:
                self.write('.')
                target = self.driver.find_element(by, value)
                if target:
                    self.writeln('done')
                    return target
            except NoSuchElementException:
                time.sleep(1)
        self.writeln('give_up')

    def find_sub_element(self, parent, by, value, element_name, seconds=30):
        self.write(f"find_sub_element {element_name}")
        for _ in range(seconds):
            try:
                self.write('.')
                target = parent.find_element(by, value)
                if target:
                    self.writeln('done')
                    return target
            except NoSuchElementException:
                time.sleep(1)
        self.writeln('give_up')

    def find_elements(self, by, value, element_name, seconds=30):
        self.write(f"find_elements {element_name}")
        for _ in range(seconds):
            try:
                self.write('.')
                target = self.driver.find_elements(by, value)
                if target:
                    self.writeln('done')
                    return target
                time.sleep(1)
            except NoSuchElementException:
                time.sleep(1)
                continue
        self.writeln('give_up')


    def find_sub_elements(self, parent, by, value, element_name, seconds=30):
        self.write(f"find_sub_elements {element_name}")
        for _ in range(seconds):
            try:
                self.write('.')
                target = parent.find_elements(by, value)
                if target:
                    self.writeln('done')
                    return target
                time.sleep(1)
            except NoSuchElementException:
                time.sleep(1)
        self.writeln('give_up')

    def find_and_click_by_class(self, class_name, element_name, seconds=30):
        self.write(f"find_and_click {element_name}")
        for _ in range(seconds):
            try:
                self.write('.')
                target = self.driver.find_element(By.CLASS_NAME, class_name)
                if target:
                    target.click()
                    self.writeln('done')
                    break
            except NoSuchElementException:
                time.sleep(1)

    def find_and_click_by_xpath(self, xpath, element_name, seconds=30):
        self.write(f"find_and_click {element_name}")
        for _ in range(seconds):
            try:
                self.write('.')
                target = self.driver.find_element(By.XPATH, xpath)
                if target:
                    target.click()
                    self.writeln('done')
                    break
            except NoSuchElementException as e:
                time.sleep(1)

    def click_by_offset(self, offset_x, offset_y, wait_secons=0.5):
        ac = ActionChains(self.driver)
        ac.reset_actions()
        ac.move_by_offset(offset_x, offset_y).click().perform()
        time.sleep(wait_secons)

    def move_by_offset(self, offset_x, offset_y):
        time.sleep(0.5)
        ac = ActionChains(self.driver)
        ac.reset_actions()
        ac.move_by_offset(offset_x, offset_y).perform()
        time.sleep(0.5)

    def click(self):
        ac = ActionChains(self.driver)
        ac.click().perform()

    def handle_dialog(self):
        try:
            push_button_yes = self.driver.find_element(By.CLASS_NAME, 'commons_pushbutton__7Tpa3')
            push_button_yes.click()
            print('found push notify, click yes', flush=True)
        except:
            pass
        for _ in range(50):
            try:
                self.driver.find_element(By.CLASS_NAME, 'GameDialog_messageBox___s2tN')
                self.driver.find_element(By.CLASS_NAME, 'GameDialog_skip__Y5RGE').click()
                print('found dialog, click skip', flush=True)
                time.sleep(0.5)
            except:
                break
        for _ in range(50):
            try:
                self.driver.find_element(By.CLASS_NAME, 'GameDialog_dialog5__ZBFqO')
                self.driver.find_element(By.CLASS_NAME, 'GameDialog_skip__Y5RGE').click()
                print('found dialog, click skip', flush=True)
                time.sleep(0.5)
            except:
                break

    def wait_page_loaded(self, seconds=60):
        self.write('wait page loaded')
        loaded = False
        for _ in range(seconds):
            try:
                self.write('.')
                self.driver.find_element(By.CLASS_NAME, 'Hud_topLeftBackground__OhgQS')
                if loaded:
                    self.writeln('done')
                    break
                else:
                    loaded = True
                    time.sleep(1)
                    continue
            except NoSuchElementException:
                loaded = False
                time.sleep(1)
        if not loaded:
            raise Exception('wait_page_load timeout')

    def escape(self):
        try:
            body = self.driver.find_element(By.TAG_NAME, 'html')
            if body is not None:
                body.send_keys(Keys.ESCAPE)
        except:
            pass

    def goto_spec(self):
        spec_home_loc = None
        for loop in range(3):
            spec_home_loc = self.image_tool.find_target('spec_home.png')
            if spec_home_loc is not None:
                home_x, home_y = spec_home_loc
                if abs(home_x - 440) < 50 and abs(home_y - 460) < 50:
                    break
                self.goto_terra()
            if loop > 0:
                self.goto_terra()
            self.escape()
            self.find_and_click_by_class("Hud_outside__zzIGQ", "LandAndBookMarks")
            time.sleep(1)
            self.find_and_click_by_class("LandAndTravel_buttonTeleport__Z6fS4", "MySpec")
            self.wait_page_loaded()
        return spec_home_loc

    def goto_task_board(self):
        for _ in range(3):
            tb_loc = self.image_tool.find_target('task_board.png')
            if tb_loc is None:
                tb_loc = (-1, -1)
            tb_x, tb_y = tb_loc
            if abs(tb_x - 330) > 50:
                self.goto_spec()
                shd_image = 'spec_house_door_new.png'
                self.movement.send_key_down(KeyCode.UP)
                for _ in range(20):
                    shd_loc = self.image_tool.find_target(shd_image)
                    if shd_loc is None:
                        continue
                    else:
                        break
                self.movement.send_key_up(KeyCode.UP)
                self.move_to_target(shd_image, delta_x=40, delta_y=120)
                self.wait_page_loaded()
                self.movement.keep_move_up(1)
            elif abs(tb_y - 545) > 50:
                self.movement.keep_move_up(1)
            else:
                break

    def goto_terra(self):
        terra_loc = self.image_tool.find_target(self.tc_image)
        if terra_loc is None:
            self.escape()
            self.find_and_click_by_class("Hud_outside__zzIGQ", "LandAndBookMarks")
            time.sleep(1)
            self.find_and_click_by_class("LandAndTravel_customHeader__goUPo", "GoToTerraVilla")
            self.wait_page_loaded()

    def goto_saona(self):
        saona_door_image = 'saona_door.png'
        target_loc = self.image_tool.find_target(saona_door_image)
        if target_loc is None:
            terra_center_image = self.tc_image
            self.goto_terra()
            terra_loc = self.image_tool.find_target(terra_center_image)
            if terra_loc is None:
                self.goto_spec()
                self.goto_terra()
                terra_loc = self.image_tool.find_target(terra_center_image)
            terra_x, terra_y = terra_loc
            if terra_y < 420:
                self.movement.keep_move_up(0.5)

            not_move = False
            for loop in range(100):
                saona_loc = self.image_tool.find_target(saona_door_image)
                if saona_loc is not None:
                    print('found saona door')
                    self.movement.send_key_up(KeyCode.LEFT)
                    break
                self.movement.send_key_down(KeyCode.LEFT)
                time.sleep(0.1)
                new_terra_loc = self.image_tool.find_target(terra_center_image)
                if new_terra_loc is not None and terra_loc == new_terra_loc:
                    if not_move:
                        not_move = False
                        self.movement.send_key_up(KeyCode.RIGHT)
                        self.movement.keep_move_right(0.1)
                        self.movement.keep_move_down(0.2)
                        self.movement.send_key_down(KeyCode.RIGHT)
                    else:
                        not_move = True
                terra_loc = new_terra_loc
                # 如果看到plot就根据plot定位
                plot_image = 'plot.png'
                plot_loc = self.image_tool.find_target(plot_image)
                if plot_loc is not None:
                    terra_loc = plot_loc
                    terra_center_image = plot_image

        self.move_to(saona_door_image, delta_x=50, delta_y=50)
        self.wait_page_loaded()

    def goto_mill(self):
        mill_image = "mill.png"
        mill_loc = self.image_tool.find_target(mill_image)
        if mill_loc is None:
            the_road_image = 'the_road.png'
            target_loc = self.image_tool.find_target(the_road_image)
            if target_loc is None:
                terra_center_image = self.tc_image
                self.goto_terra()
                terra_loc = self.image_tool.find_target(terra_center_image)
                if terra_loc is None:
                    self.goto_spec()
                    self.goto_terra()
                    terra_loc = self.image_tool.find_target(terra_center_image)
                terra_x, terra_y = terra_loc
                if terra_y < 420:
                    self.movement.keep_move_up(0.5)

                not_move = False
                for loop in range(100):
                    the_road_loc = self.image_tool.find_target(the_road_image)
                    if the_road_loc is not None:
                        print('found the road sign')
                        self.movement.send_key_up(KeyCode.LEFT)
                        break
                    self.movement.send_key_down(KeyCode.LEFT)
                    time.sleep(0.1)
                    new_terra_loc = self.image_tool.find_target(terra_center_image)
                    if new_terra_loc is not None and terra_loc == new_terra_loc:
                        if not_move:
                            not_move = False
                            self.movement.send_key_up(KeyCode.RIGHT)
                            self.movement.keep_move_right(0.1)
                            self.movement.keep_move_down(0.2)
                            self.movement.send_key_down(KeyCode.RIGHT)
                        else:
                            not_move = True
                    terra_loc = new_terra_loc
                    # 如果看到plot就根据plot定位
                    plot_image = 'plot.png'
                    plot_loc = self.image_tool.find_target(plot_image)
                    if plot_loc is not None:
                        terra_loc = plot_loc
                        terra_center_image = plot_image

            self.move_to(the_road_image, delta_x=200, delta_y=-100, max_loop=5)
            self.movement.move_left(1)
            for _ in range(5):
                mill_loc = self.image_tool.find_target(mill_image)
                if mill_loc is None:
                    self.movement.keep_move_up(2)

        self.move_to(mill_image, max_loop=3)

        return self.image_tool.find_target(mill_image)

    def move_to(self, move_target_image, threshold=0.8, delta_x=-10, delta_y=0, max_loop=None):
        init_loc = self.image_tool.find_target(move_target_image)
        if init_loc is None:
            return
        init_x, init_y = init_loc
        ac = ActionChains(self.driver)
        ac.reset_actions()
        ac.move_by_offset(init_x + delta_x, init_y + delta_y).click_and_hold().perform()
        time.sleep(1)
        not_move = False
        for loop in range(100):
            new_loc = self.image_tool.find_nearest_target(
                move_target_image,
                threshold=threshold,
                near_x=init_x,
                near_y=init_y
            )
            if max_loop is not None and loop >= max_loop:
                ac.release().perform()
                break
            if new_loc is None:
                ac.release().perform()
                break
            else:
                new_x, new_y = new_loc
                offset_x = new_x - init_x
                offset_y = new_y - init_y
                init_x = new_x
                init_y = new_y
                if offset_x == 0 and offset_y == 0:
                    if max_loop is not None:
                        continue
                    if not_move:
                        ac.release().perform()
                        self.movement.keep_move_left(0.5)
                        self.movement.keep_move_down(0.5)
                        self.move_to(move_target_image, threshold, delta_x, delta_y, max_loop)
                        break
                    else:
                        not_move = True
                ac.move_by_offset(offset_x, offset_y)

    def move_to_target(self, move_target_image, delta_x=-10, delta_y=0):
        init_loc = self.image_tool.find_target(move_target_image)
        if init_loc is None:
            return
        init_x, init_y = init_loc
        ac = ActionChains(self.driver)
        ac.reset_actions()
        init_x = max(init_x + delta_x, 0)
        init_y = max(init_y + delta_y, 0)
        ac.move_by_offset(init_x, init_y).click_and_hold().perform()
        time.sleep(1)
        for _ in range(50):
            new_loc = self.image_tool.find_target(move_target_image)
            if new_loc is None:
                ac.release().perform()
                break
            else:
                new_x, new_y = new_loc
                new_x = new_x + delta_x
                new_y = new_y + delta_y
                offset_x = new_x - init_x
                offset_y = new_y - init_y
                init_x = new_x
                init_y = new_y
                if offset_x == 0 and offset_y == 0:
                    ac.release().perform()
                    break
                ac.move_by_offset(offset_x, offset_y)
                time.sleep(0.5)

    def goto_shop(self):
        shop_door_image = 'shop_door.png'
        shop_loc = self.image_tool.find_target(shop_door_image)
        if shop_loc is None:
            terra_center_image = self.tc_image
            self.goto_terra()
            terra_loc = self.image_tool.find_target(terra_center_image)
            if terra_loc is None:
                self.goto_spec()
                self.goto_terra()

            for _ in range(10):
                terra_loc = self.image_tool.find_target(terra_center_image)
                terra_x, terra_y = terra_loc
                if terra_y < 410:
                    self.movement.keep_move_up(0.5)
                    continue
                if terra_y > 560:
                    self.movement.keep_move_down(0.5)
                    continue
                break
            not_move = False
            for loop in range(20):
                shop_loc = self.image_tool.find_target(shop_door_image)
                if shop_loc is not None:
                    print('found shop door')
                    self.movement.send_key_up(KeyCode.RIGHT)
                    break
                self.movement.send_key_down(KeyCode.RIGHT)
                time.sleep(0.1)
                new_terra_loc = self.image_tool.find_target(terra_center_image)
                if new_terra_loc is not None and terra_loc == new_terra_loc:
                    if not_move:
                        not_move = False
                        self.movement.send_key_up(KeyCode.RIGHT)
                        self.movement.keep_move_left(0.1)
                        self.movement.keep_move_down(0.2)
                        self.movement.send_key_down(KeyCode.RIGHT)
                    else:
                        not_move = True
                terra_loc = new_terra_loc
        time.sleep(0.5)
        for _ in range(3):
            shop_loc = self.image_tool.find_target(shop_door_image)
            if shop_loc:
                shop_x, shop_y = shop_loc
                if shop_x < 650:
                    self.movement.keep_move_left(0.2)
                time.sleep(1)
            else:
                self.goto_spec()
                return
        self.move_to(shop_door_image, delta_x=100, delta_y=30)
        self.wait_page_loaded()
        self.handle_dialog()

    def goto_hq(self):
        hq_door_image = 'pixels_hq.png'
        hq_loc = self.image_tool.find_target(hq_door_image)
        if hq_loc is None:
            terra_center_image = self.tc_image
            self.goto_terra()
            terra_loc = self.image_tool.find_target(terra_center_image)
            if terra_loc is None:
                self.goto_spec()
                self.goto_terra()
                terra_loc = self.image_tool.find_target(terra_center_image)

            not_move = False
            for loop in range(100):
                hq_loc = self.image_tool.find_target(hq_door_image)
                if hq_loc is not None:
                    print('found hq door')
                    self.movement.send_key_up(KeyCode.UP)
                    break
                self.movement.send_key_down(KeyCode.UP)
                time.sleep(0.1)
                new_terra_loc = self.image_tool.find_target(terra_center_image)
                if new_terra_loc is not None and terra_loc == new_terra_loc:
                    if not_move:
                        not_move = False
                        self.movement.send_key_up(KeyCode.UP)
                        self.movement.keep_move_down(0.1)
                        self.movement.keep_move_right(0.3)
                        self.movement.send_key_down(KeyCode.UP)
                    else:
                        not_move = True
                terra_loc = new_terra_loc
        self.move_to(hq_door_image)
        self.wait_page_loaded()

    def goto_land(self, land_no):
        self.escape()
        self.find_and_click_by_class("Hud_outside__zzIGQ", "LandAndBookMarks")
        time.sleep(1)
        my_bookmarks_path = f"//img[@src='https://d31ss916pli4td.cloudfront.net/game/assets/landandtravel/bookmark_inactive.png']"
        self.find_and_click_by_xpath(my_bookmarks_path, "MyBookmarks")
        self.write(f"find_and_click_land #{land_no}:")
        for _ in range(3):
            try:
                self.write('.')
                go_button_path = f"//div[contains(text(), '#{land_no}')]/following-sibling::button"
                target = self.driver.find_element(By.XPATH, go_button_path)
                if target:
                    time.sleep(1)
                    target.click()
                    self.writeln('done')
                    break
            except NoSuchElementException:
                Log('notify').info(f'[{self.user_id}] land_no [{land_no}] not in bookmarks')
                time.sleep(1)
        self.wait_page_loaded()

    def goto_land_from_portal(self,land_no, bookmark=False):
        saona_door_image = 'saona_door.png'
        target_loc = self.image_tool.find_target(saona_door_image)
        if target_loc is None:
            terra_center_image = self.tc_image
            self.goto_terra()
            terra_loc = self.image_tool.find_target(terra_center_image)
            if terra_loc is None:
                self.goto_spec()
                self.goto_terra()
                terra_loc = self.image_tool.find_target(terra_center_image)
            terra_x, terra_y = terra_loc
            if terra_y < 420:
                self.movement.keep_move_up(0.5)

            not_move = False
            for loop in range(100):
                target_loc = self.image_tool.find_target(saona_door_image)
                if target_loc is not None:
                    self.movement.send_key_up(KeyCode.LEFT)
                    break
                self.movement.send_key_down(KeyCode.LEFT)
                time.sleep(0.1)
                new_terra_loc = self.image_tool.find_target(terra_center_image)
                if new_terra_loc is not None and terra_loc == new_terra_loc:
                    if not_move:
                        not_move = False
                        self.movement.send_key_up(KeyCode.RIGHT)
                        self.movement.keep_move_right(0.1)
                        self.movement.keep_move_down(0.2)
                        self.movement.send_key_down(KeyCode.RIGHT)
                    else:
                        not_move = True
                terra_loc = new_terra_loc
                # 如果看到plot就根据plot定位
                plot_image = 'plot.png'
                plot_loc = self.image_tool.find_target(plot_image)
                if plot_loc is not None:
                    terra_loc = plot_loc
                    terra_center_image = plot_image
        land_office_door_image = 'land_office.png'
        for _ in range(3):
            land_office_loc = self.image_tool.find_target(land_office_door_image)
            if land_office_loc:
                break
            self.movement.keep_move_right(0.5)
        time.sleep(0.5)
        self.move_to(land_office_door_image)
        self.wait_page_loaded()
        self.move_to('land_office_spec.png', delta_x=500, max_loop=6)
        self.move_to('land_office_plot.png', delta_y=-400, max_loop=4)
        self.move_by_offset(300, 300)
        portal_x, portal_y = self.image_tool.find_target('infini_portal_center.png')

        self.click_by_offset(portal_x, portal_y)
        portal_input = self.find_element(By.CLASS_NAME, 'LandAndTravel_numberInput__Re9sf', 'PortalInput')
        time.sleep(0.5)
        portal_input.send_keys(str(land_no))
        time.sleep(0.5)
        portal_input.send_keys(Keys.ENTER)
        self.wait_page_loaded()

    def hover_bubble_text_is(self, hover_x, hover_y, target_text):
        for _ in range(4):
            self.move_by_offset(hover_x, hover_y)
            for _ in range(4):
                target = self.find_element(By.CLASS_NAME, 'LookAtBubble_lookAtBubble___pd4a', None, 1)
                if target is None:
                    time.sleep(0.5)
                    continue
                else:
                    return target_text == target.text
        return False

    def hover_bubble_text_has(self, hover_x, hover_y, target_text):
        for _ in range(4):
            self.move_by_offset(hover_x, hover_y)
            for _ in range(4):
                target = self.find_element(By.CLASS_NAME, 'LookAtBubble_lookAtBubble___pd4a', None, 1)
                if target is None:
                    time.sleep(0.5)
                    continue
                else:
                    return target_text in target.text
        return False

    def hover_bubble(self,hover_x, hover_y):
        try:
            self.move_by_offset(hover_x, hover_y)
            time.sleep(0.5)
            target = self.find_element(By.CLASS_NAME, 'LookAtBubble_lookAtBubble___pd4a', None, 1)
            if target is not None:
                return target.text
            return None
        except:
            return None

    def goto_wine_house(self):
        wh_image = 'wine_house.png'
        wh_loc = self.image_tool.find_target(wh_image)
        if wh_loc is None:
            self.goto_terra()
            ac = ActionChains(self.driver)
            tc_loc = self.image_tool.find_target(self.tc_image)
            if tc_loc is None:
                self.goto_spec()
                self.goto_terra()
                tc_loc = self.image_tool.find_target(self.tc_image)

            tc_x, tc_y = tc_loc
            if tc_x <= 300:
                self.movement.keep_move_left(2)

            vs_image = 'vip_store_new.png'

            for _ in range(5):
                vs_loc = self.image_tool.find_target(vs_image)
                if vs_loc is None:
                    self.movement.move_left(1)
                    self.movement.keep_move_down(1)
                else:
                    vs_x, vs_y = vs_loc
                    if vs_x > 800:
                        self.movement.keep_move_down(0.5)
                    if vs_y < 100:
                        self.movement.keep_move_left(0.5)
                    break

            vs_loc = self.image_tool.find_target(vs_image)
            init_x, init_y = vs_loc
            try:
                ac.reset_actions()
                ac.move_by_offset(init_x + 50, init_y+50).click_and_hold().perform()
                for _ in range(5):
                    new_loc = self.image_tool.find_target(vs_image)
                    if new_loc is not None:
                        new_x, new_y = new_loc
                        offset_x = new_x - init_x + 10
                        offset_y = new_y - init_y + 50
                        init_x = new_x
                        init_y = new_y
                        ac.move_by_offset(offset_x, offset_y).perform()
            except Exception as e:
                pass
            finally:
                ac.release().perform()
            self.movement.keep_move_down(1)
            self.movement.keep_move_right(0.5)

            corner_image = 'corner.png'
            for _ in range(100):
                corner_loc = self.image_tool.find_target(corner_image)
                if corner_loc is not None:
                    print('see corner')
                    break
                self.movement.send_key_down(KeyCode.DOWN)

            self.movement.send_key_up(KeyCode.DOWN)
            # corner_loc = self.image_tool.find_target(corner_image)
            # corner_x, corner_y = corner_loc
            #
            # ac.reset_actions()
            # ac.move_by_offset(corner_x, corner_y).click_and_hold().perform()
            # for _ in range(8):
            #     new_loc = self.image_tool.find_target(corner_image)
            #     if new_loc is not None:
            #         new_x, new_y = new_loc
            #         corner_x = new_x
            #         corner_y = new_y
            #         ac.move_by_offset(new_x - corner_x, new_y - corner_y).perform()
            #
            # ac.release().perform()
            self.movement.keep_move_down(2)
            self.movement.send_key_down(KeyCode.LEFT)
            for _ in range(100):
                wh_loc = self.image_tool.find_target(wh_image)
                if wh_loc is not None:
                    break
            self.movement.send_key_up(KeyCode.LEFT)
            time.sleep(1)
            wh_loc = self.image_tool.find_target(wh_image)
            wh_x, wh_y = wh_loc
            if wh_y > 800:
                self.movement.keep_move_down(1)
            self.move_to(wh_image, delta_x=150, delta_y=50, max_loop=3)
        time.sleep(1)
        return self.image_tool.find_target(wh_image)

    def goto_textile_station(self):
        ts_image = 'textile_car.png'
        ts_loc = self.image_tool.find_target(ts_image)
        if ts_loc is None:
            self.goto_terra()
            ac = ActionChains(self.driver)
            tc_loc = self.image_tool.find_target(self.tc_image)
            if tc_loc is None:
                self.goto_spec()
                self.goto_terra()
                tc_loc = self.image_tool.find_target(self.tc_image)

            tc_x, tc_y = tc_loc
            if tc_x <= 300:
                self.movement.keep_move_left(2)

            vs_image = 'vip_store_new.png'

            for _ in range(5):
                vs_loc = self.image_tool.find_target(vs_image)
                if vs_loc is None:
                    self.movement.move_left(1)
                    self.movement.keep_move_down(1)
                else:
                    vs_x, vs_y = vs_loc
                    if vs_x > 800:
                        self.movement.keep_move_down(0.5)
                    if vs_y < 100:
                        self.movement.keep_move_left(0.5)
                    break

            vs_loc = self.image_tool.find_target(vs_image)
            init_x, init_y = vs_loc
            try:
                ac.reset_actions()
                ac.move_by_offset(init_x + 50, init_y + 50).click_and_hold().perform()
                for _ in range(5):
                    new_loc = self.image_tool.find_target(vs_image)
                    if new_loc is not None:
                        new_x, new_y = new_loc
                        offset_x = new_x - init_x + 10
                        offset_y = new_y - init_y + 50
                        init_x = new_x
                        init_y = new_y
                        ac.move_by_offset(offset_x, offset_y).perform()
            except Exception as e:
                pass
            finally:
                ac.release().perform()
            self.movement.keep_move_down(1)
            self.movement.keep_move_right(0.5)

            corner_image = 'corner.png'
            for _ in range(100):
                corner_loc = self.image_tool.find_target(corner_image)
                if corner_loc is not None:
                    corner_x, corner_y = corner_loc
                    if corner_y <= 850:
                        print('see corner')
                        self.movement.send_key_up(KeyCode.DOWN)
                        break
                self.movement.send_key_down(KeyCode.DOWN)
            self.movement.send_key_up(KeyCode.DOWN)
            self.movement.keep_move_down(1)
            self.movement.send_key_down(KeyCode.RIGHT)
            for _ in range(100):
                wh_loc = self.image_tool.find_target(ts_image)
                if wh_loc is not None:
                    break
            self.movement.send_key_up(KeyCode.RIGHT)
        time.sleep(1)
        self.move_to(ts_image, delta_x=-80, max_loop=3)
        time.sleep(1)
        return self.image_tool.find_target('tex.png')

    def goto_moi(self):
        moi_image = 'moi.png'
        moi_loc = self.image_tool.find_target(moi_image)
        if moi_loc is None:
            self.goto_terra()
            ac = ActionChains(self.driver)
            tc_loc = self.image_tool.find_target(self.tc_image)
            if tc_loc is None:
                self.goto_spec()
                self.goto_terra()
                tc_loc = self.image_tool.find_target(self.tc_image)

            tc_x, tc_y = tc_loc
            if tc_x <= 300:
                self.movement.keep_move_left(2)

            vs_image = 'vip_store_new.png'

            for _ in range(5):
                vs_loc = self.image_tool.find_target(vs_image)
                if vs_loc is None:
                    self.movement.move_left(1)
                    self.movement.keep_move_down(1)
                else:
                    vs_x, vs_y = vs_loc
                    if vs_x > 800:
                        self.movement.keep_move_down(0.5)
                    if vs_y < 100:
                        self.movement.keep_move_left(0.5)
                    break

            vs_loc = self.image_tool.find_target(vs_image)
            init_x, init_y = vs_loc
            try:
                ac.reset_actions()
                ac.move_by_offset(init_x + 50, init_y + 50).click_and_hold().perform()
                for _ in range(5):
                    new_loc = self.image_tool.find_target(vs_image)
                    if new_loc is not None:
                        new_x, new_y = new_loc
                        offset_x = new_x - init_x + 10
                        offset_y = new_y - init_y + 50
                        init_x = new_x
                        init_y = new_y
                        ac.move_by_offset(offset_x, offset_y).perform()
            except Exception as e:
                pass
            finally:
                ac.release().perform()
            self.movement.keep_move_down(1)
            self.movement.keep_move_right(0.5)

            corner_image = 'corner.png'
            for _ in range(100):
                corner_loc = self.image_tool.find_target(corner_image)
                if corner_loc is not None:
                    corner_x, corner_y = corner_loc
                    if corner_y <= 800:
                        print('see corner')
                        self.movement.send_key_up(KeyCode.DOWN)
                        break
                self.movement.send_key_down(KeyCode.DOWN)

            self.movement.keep_move_down(1)
            self.movement.keep_move_left(1.5)
            self.movement.keep_move_up(2)
            self.movement.keep_move_up(2)

            for _ in range(10):
                moi_loc = self.image_tool.find_target('moi_door.png')
                if moi_loc is None:
                    break
                else:
                    moi_x, moi_y = moi_loc
                    if moi_x > 450:
                        self.movement.move_right(1, 0.1)
                        time.sleep(0.5)
                    else:
                        self.movement.move_left(1, 0.1)
                        time.sleep(0.5)

        self.wait_page_loaded()
        self.movement.keep_move_up(1)
        time.sleep(2)
        return self.image_tool.find_target(moi_image)
